package com.mi.rule.log;

import com.alibaba.fastjson.JSON;
import com.mi.rule.resource.ResM;
import com.mi.rule.util.EnvKit;
import com.mi.rule.util.HttpKit;
import com.mi.rule.util.project.MiException;
import com.mi.rule.util.project.SRS;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * 请求日志处理器
 */
@Slf4j
@Aspect
@Component
public class RequestLogHandler {
    //过滤
    @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
    public void pointcut() {
    }
    //    切点规则
    //    @Pointcut("execution(* com.soul.module.*.controller.*.*(..))")
    //    public void pointcut() {
    //    }

    //  切面
    @Around("pointcut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        //输出已关闭
        if (!EnvKit.showRequestLog()) return point.proceed();
        //        ReqLog resLog = ((MethodSignature) point.getSignature()).getMethod().getAnnotation(ReqLog.class);
        ResM res = ((MethodSignature) point.getSignature()).getMethod().getAnnotation(ResM.class);
        HttpServletRequest request = HttpKit.request();
        if (request == null) {
            return point.proceed();
        }
        long beginTime = System.currentTimeMillis();
        String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss:SSS"));
        System.out.println("\n");
        log.info("========================================== Start ==========================================");
        log.info("URI          ：{}", request.getRequestURI());
        log.info("URL          ：{}", request.getRequestURL());
        if (res != null) {
            log.info("Name  ：{}", res.value());
        }
        log.info("Method       ：{}.{}", point.getTarget().getClass().getName(), point.getSignature().getName());
        try {
            log.info("Param        ：{}", JSON.toJSONString(point.getArgs()));
        } catch (Exception e) {
            log.info("Param        ：{}", point.getArgs());
        }
        log.info("Start        ：{}", time);
        log.info("Type-IP      ：{} - {}", request.getMethod(), HttpKit.getIpAddr(request));
        log.info("Headers      ：{}", JSON.toJSONString(HttpKit.requestHeaders(request)));
        Object response = null;
        //执行
        try {
            response = point.proceed();
        }
        //已知异常
        catch (MiException e) {
            response = e.getResponse();
            log.error(ExceptionUtils.getStackTrace(e));
            throw e;
        }
        //未知异常
        catch (Throwable e) {
            response = SRS.byError();
            log.error(ExceptionUtils.getStackTrace(e));
            throw e;
        }
        //执行结束
        finally {
            double executionTime = Double.parseDouble((System.currentTimeMillis() - beginTime) + "") / 1000;
            log.info("Response     ：{}", JSON.toJSONString(response));
            log.info("Execute Time ：{} 秒", executionTime);
            log.info("=========================================== End ===========================================\n");
//            String timeEnd = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss:SSS"));
//            log.info("URI          ：{}", request.getRequestURI());
//            log.info("URL          ：{}", request.getRequestURL());
//            log.info("Start        ：{}", time);
//            log.info("End          ：{}", timeEnd);
        }
        return response;
    }

    //方法执行前
    @Before("pointcut()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
    }

    /**
     * 方法执行后
     */
    @After("pointcut()")
    public void doAfter() throws Throwable {
    }

}
